package org.misty.seckill.controller;

import org.misty.seckill.model.User;
import org.misty.seckill.rabbitmq.MqSender;
import org.misty.seckill.rabbitmq.SeckillMessage;
import org.misty.seckill.redis.GoodsKey;
import org.misty.seckill.redis.RedisService;
import org.misty.seckill.service.GoodsService;
import org.misty.seckill.service.SeckillService;
import org.misty.seckill.status.SeckillCode;
import org.misty.seckill.util.SnowflakeIdWorker;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/seckill")
public class SeckillController implements InitializingBean {
  @Autowired
  private GoodsService goodsService;
  @Autowired
  private SeckillService seckillService;
  @Autowired
  private RedisService redisService;
  @Autowired
  private MqSender mqSender;
  @Autowired
  private SnowflakeIdWorker snowflake;

  @Override
  public void afterPropertiesSet() {
    seckillService.putAllOnSale();
  }

  /**
   * 2020-05-06  QPS 6400  1000c * 50 (100 connections)
   * 2020-05-06  QPS 5900  2000c * 25 (200 connections)
   */
  @PostMapping("/{id:\\d+}")
  @ResponseBody
  public Map<String, Object> seckill(@PathVariable long id, @RequestAttribute("user") User user, HttpServletResponse response) {
    var res = new HashMap<String, Object>();
    var qid = snowflake.nextId();
    var code = seckillService.placeOrder(user, id, qid);
    if (code != 1) {
      res.put("error", code);
      return res;
    }
    var msg = new SeckillMessage(user, id, qid);
    mqSender.sendSeckill(msg);
    res.put("success", "排队中");
    res.put("qid", String.valueOf(qid));
    response.setStatus(HttpServletResponse.SC_ACCEPTED);
    return res;
  }

  @PostMapping("/queuing")
  @ResponseBody
  public Map<String, Object> queuing(long id, @RequestAttribute("user") User user, HttpServletResponse response) throws IOException {
    var res = new HashMap<String, Object>();
    var key = GoodsKey.queuingKey(user.getId(), id);
    var r = redisService.get(GoodsKey.SECKILL_QUEUING, key);
    if (StringUtils.isEmpty(r)) {
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
    } else {
      var ary = r.split("\\|");
      var code = Integer.parseInt(ary[0]);
      res.put("code", code);
      if (code == SeckillCode.SUCCESS) {
        res.put("success", true);
        res.put("orderId", ary[1]);
      } else if (code == 0) {
        res.put("waiting", true);
      } else {
        res.put("error", true);
      }
    }
    res.put("result", r);
    return res;
  }

  @GetMapping("/orders/{id:\\d+}")
  @ResponseBody
  public Map<String, Object> getOrder(@PathVariable long id, @RequestAttribute("user") User user,
                                      HttpServletResponse response) throws IOException {
    System.out.println(id);
    var ret = new HashMap<String, Object>();
    var order = seckillService.getOrderById(user, id);
    if (order != null) {
      ret.put("order", order);
      var goods = goodsService.getDetailByOid(order.getId());
      ret.put("goods", goods);
    } else {
      response.sendError(HttpServletResponse.SC_NOT_FOUND, "没有这个订单：" + id);
    }
    return ret;
  }

  @GetMapping("/reset")
  @ResponseBody
  public boolean reset() {
    seckillService.reset();
    return true;
  }
}
